import React, { createContext, useContext, useImperativeHandle, useState } from 'react';
import PropTypes from 'prop-types';
import { Button, Form, Spin, message, Icon, Divider } from 'antd';
import classNames from 'classnames';
import styles from './index.less';

const FormContext = createContext();

/**
 * 表单容器
 */
const FormContainer = React.forwardRef(
    (
        {
            form,
            title,
            onSubmit,
            onCancel,
            onEdit,
            hasEditAuth,
            formItemLayout,
            defaultEdit,
            flexLayout,
            children,
            ...props
        },
        ref
    ) => {
        // 编辑状态
        const [editStatus, setEditStatus] = useState(!!defaultEdit);
        const [loading, setLoading] = useState(false);

        // 保存
        const handleSubmit = e => {
            e.preventDefault();
            form.validateFields(async (errors, values) => {
                if (!errors && onSubmit) {
                    try {
                        setLoading(true);
                        await onSubmit(values, form);
                        setLoading(false);
                        setEditStatus(false);
                    } catch (error) {
                        setLoading(false);
                        message.error(error.message);
                    }
                }
            });
        };

        // 取消编辑
        const handleCancel = () => {
            if (onCancel) {
                const cancelResult = onCancel();
                if (cancelResult !== false) {
                    setEditStatus(false);
                    form.resetFields();
                }
            } else {
                setEditStatus(false);
                form.resetFields();
            }
        };

        // 编辑
        const handleEdit = () => {
            if (onEdit) {
                onEdit();
            }
            setEditStatus(true);
        };

        useImperativeHandle(ref, () => ({
            form
        }));

        // 渲染编辑按钮, 要判断是否有权限
        const renderEditButton = () =>
            hasEditAuth ? (
                <Button className="edit" type="link" size="small" onClick={handleEdit}>
                    <Icon type="edit" />
                    编辑
                </Button>
            ) : null;

        // 渲染控制栏
        const renderControls = () => {
            if (props.customControls) {
                return props.customControls({ editStatus, loading, handleSubmit, handleCancel });
            }
            if (onSubmit) {
                if (editStatus) {
                    return (
                        <div>
                            <Button type="link" size="small" onClick={handleSubmit} loading={loading}>
                                <Icon type="check" />
                                保存
                            </Button>
                            <Divider type="vertical" />
                            <Button type="link" size="small" onClick={handleCancel}>
                                <Icon type="close" />
                                取消
                            </Button>
                            &emsp;
                        </div>
                    );
                }
                return renderEditButton();
            }
            return null;
        };

        // render
        return (
            <Spin spinning={loading}>
                <FormContext.Provider value={{ editStatus }}>
                    <div className={classNames(styles.formSection, flexLayout && styles.formSectionFlex)}>
                        {title && <div className={styles.sectionHeader}>{title}</div>}
                        <div className={styles.sectionControls}>{renderControls()}</div>
                        <Form {...formItemLayout} className={editStatus ? styles.formEdit : styles.formView}>
                            {children(form, editStatus)}
                        </Form>
                    </div>
                </FormContext.Provider>
            </Spin>
        );
    }
);

// prop
FormContainer.propTypes = {
    title: PropTypes.any,
    onSubmit: PropTypes.func,
    onCancel: PropTypes.func,
    hasEditAuth: PropTypes.bool,
    defaultEdit: PropTypes.bool,
    formItemLayout: PropTypes.object,
    customControls: PropTypes.func,
    flexLayout: PropTypes.bool
};

FormContainer.defaultProps = {
    title: null,
    onSubmit: null,
    onCancel: null,
    hasEditAuth: true,
    defaultEdit: false,
    formItemLayout: {
        labelCol: {
            md: { span: 8 },
            xs: { span: 24 },
            sm: { span: 24 }
        },
        wrapperCol: {
            md: { span: 15 },
            xs: { span: 24 },
            sm: { span: 24 }
        }
    },
    customControls: null,
    flexLayout: false
};

FormContainer.displayName = 'FormContainer';

export default Form.create()(FormContainer);

export const fullRowFormItemLayout = {
    labelCol: {
        md: { span: 4 },
        xs: { span: 24 },
        sm: { span: 24 }
    },
    wrapperCol: {
        md: { span: 19 },
        xs: { span: 24 },
        sm: { span: 24 }
    }
};

export const FormItem = params => {
    const formContext = useContext(FormContext);
    const { label, show = true, normalComponent, editComponent, required, ...otherProps } = params;
    const { editStatus } = formContext;
    if (!show) {
        return null;
    }
    return (
        <Form.Item label={label} {...otherProps} required={editStatus && editComponent && required}>
            {editStatus && editComponent ? editComponent() : normalComponent()}
        </Form.Item>
    );
};
FormItem.displayName = 'FormItem';

export const FormTitle = ({ title }) => <div className={styles.sectionHeader}>{title}</div>;
FormTitle.displayName = 'FormTitle';
